package com.dataextend.service;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dataextend.entity.UserGroupRequest;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

/**
 *   用户人群计算模型 (仅基于标签组合计算-标签存储在elasticsearch)
 */
@Service
public class UserGroupCalculateService {
    @Autowired
    RestHighLevelClient restHighLevelClient;
    @Value("${usertag_all.usertag_all.index}")
    private String usertagIndex;
    @Value("${usertag_all.usertag_all.source_field}")
    private String usertagSourceField;
    @Value("${usertag_all.usertag_all.type}")
    private String type;

    /**
     *  Elasticsearch数据结构   userid,tagsmap,datadate
     *
     *  {"B121H030_0_001":"","A121H030_0_021":"2","A334H030_0_001":"66.5"}
     *  入参格式
     *     "relationship":"and",
     *     "ruledetails":[{"key":"A121H030_0_021","value":"[1,5]"},
     *                    {"key":"A332H034_0_021","value":""},
     *                    {"key":"B151H001_0_021","value":"[6,]"},
     *                    {"key":"B041H012_0_021","value":"[,7]"},
     *                    ....
     *                    ]
     */

    // 解析人群规则
    private Long parseRule(String ruleInfo, String isSave){
        System.out.println("  " + ruleInfo + "  " + isSave);
        //创建搜索请求对象
        SearchRequest searchRequest = new SearchRequest(usertagIndex);
        String[] source_field_array = usertagSourceField.split(",");

        //设置搜索类型
        searchRequest.types(type);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.fetchSource(source_field_array, new String[]{});
        //创建布尔查询对象
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        BoolQueryBuilder query = QueryBuilders.boolQuery();

        JSONObject ruleInfos = JSON.parseObject(ruleInfo);
        // 判断条件之间的关联关系
        String relationship = (String) ruleInfos.get("relationship");
        List ruledetails = (List) ruleInfos.get("ruledetails");

        // 在这里对查询条件进行详细解析和判断
        for (Object ruledetail : ruledetails) {
            JSONObject job = (JSONObject) ruledetail;
            System.out.println("  JSONObject job: " + job);
            String key = job.getString("key");
            String value = job.getString("value");
            if (value== null || value.equals("")){
                // 空值 没有权重
                String parameter = "tagsmap." + key;
                if (relationship.equals("and")){
                    boolQueryBuilder.must(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.existsQuery(parameter)), ScoreMode.None));
                } else {
                    query.should(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.existsQuery(parameter)), ScoreMode.None));
                }
            } else if (value.split(",")[0].replace("[","").equals("")){
                // 小于等于 [,7]
                String parameter = "tagsmap." + key;
                String maxvalue = value.split(",")[1].replace("]","");
                if (relationship.equals("and")){
                    boolQueryBuilder.must(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).lte(maxvalue)), ScoreMode.None));
                } else {
                    query.should(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).lte(maxvalue)), ScoreMode.None));
                }
            }else if (value.split(",")[1].replace("]","").equals("")) {
                // 大于等于 [6,]
                String parameter = "tagsmap." + key;
                String minvalue = value.split(",")[0].replace("[","");
                if (relationship.equals("and")){
                    boolQueryBuilder.must(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).gte(minvalue)), ScoreMode.None));
                } else {
                    query.should(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).gte(minvalue)), ScoreMode.None));
                }
            } else {
                // 两边都有值 [1,5]
                String maxvalue = value.split(",")[1].replace("]","");
                String minvalue = value.split(",")[0].replace("[","");
                String parameter = "tagsmap." + key;
                if (key.equals("and")){
                    boolQueryBuilder.must(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).from(minvalue).to(maxvalue)), ScoreMode.None));
                } else {
                    query.should(QueryBuilders.nestedQuery("tagsmap", QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery(parameter).from(minvalue).to(maxvalue)), ScoreMode.None));
                }
            }
        }

        boolQueryBuilder.must(query);
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);

        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
            SearchHits hits = searchResponse.getHits();
            return hits.totalHits;
        } catch (IOException e){
            e.printStackTrace();
        }

        return null;
    }



    /**
     *  查询
     */
    public JSONObject usergroupCalculate(UserGroupRequest userGroupRequest){
        // 圈人规则,日期参数,是否导出文件
        JSONObject result = new JSONObject(true);
        Long userCount = parseRule(userGroupRequest.getRuleinfo(), userGroupRequest.getIssave());
        System.out.println("this group user count: " + userCount);
        result.put("total", userCount);
        return result;
    }

}
